import { Tool } from '../../../Tool';

/**
 * 立方体剖切
 */
export class ClipByBoxTool extends Tool {
	constructor(viewer) {
		super(arguments);
		this.viewer = viewer;
		this.mode = 0; // 0 - 自绘制剖切盒子， 1 - 使用生成包围盒（单图层-默认第一个-可设置图层名）， 2 - 使用生成包围盒（多图层-可限制）
		this.clipLayerLimited = [];
		this.dataSource = new Cesium.CustomDataSource('fe-clipbybox');
		this.viewer.dataSources.add(this.dataSource);
		viewer.scene.layers.layerQueue.forEach((item) => {
			item.selectEnabled = false;
			item.releaseSelection();
		});
	}

	clearLayersClipOptions() {
		for (const layer of this.clipLayers) {
			layer.clearCustomClipBox();
		}
	}

	setLayersClipOptions(boxOptions) {
		for (const layer of this.clipLayers) {
			layer.setCustomClipBox(boxOptions);
		}
	}

	setClipBox(boxEntity) {
		if (typeof boxEntity === 'undefined') {
			return;
		}
		const newDim = boxEntity.box.dimensions.getValue();
		const position = boxEntity.position.getValue(0);
		let heading = 0;
		if (typeof boxEntity.orientation !== 'undefined') {
			const rotationM3 = Cesium.Matrix3.fromQuaternion(
				boxEntity.orientation._value,
				new Cesium.Matrix3()
			);
			const localFrame = Cesium.Matrix4.fromRotationTranslation(
				rotationM3,
				Cesium.Cartesian3.ZERO,
				new Cesium.Matrix4()
			);
			const inverse = Cesium.Matrix4.inverse(
				Cesium.Transforms.eastNorthUpToFixedFrame(position),
				new Cesium.Matrix4()
			);
			const hprm = Cesium.Matrix4.multiply(inverse, localFrame, new Cesium.Matrix4());
			const rotation = Cesium.Matrix4.getMatrix3(hprm, new Cesium.Matrix3());
			const hpr = Cesium.HeadingPitchRoll.fromQuaternion(
				Cesium.Quaternion.fromRotationMatrix(rotation)
			);
			heading = hpr.heading;
		}
		const boxOptions = {
			dimensions: newDim,
			position: position,
			clipMode: 'clip_behind_any_plane',
			heading: heading
		};
		this.setLayersClipOptions(boxOptions);
	}

	setEditBox(boxEntity) {
		if (typeof boxEntity === 'undefined') {
			return;
		}
		var _that = this;
		var newDim = boxEntity.box.dimensions.getValue();
		var position = boxEntity.position.getValue(0);
		var boxOption = {
			dimensions: newDim,
			position: position,
			clipMode: 'clip_behind_any_plane',
			heading: 0
		};
		this.viewer.clipBox && this.viewer.clipBox.deactivate();
		this.viewer.clipBox = new Cesium.BoxEditor(this.viewer, boxEntity);
		this.viewer.clipBox.editEvt.addEventListener(function (e) {
			boxEntity.box.dimensions = e.dimensions;
			boxEntity.position = e.position;
			boxEntity.orientation = e.orientation;
			_that.setClipBox(boxEntity);
		});
		this.viewer.clipBox.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(0, 80000);
		this.viewer.clipBox.activate();
		_that.setLayersClipOptions(boxOption);
	}

	getBoundingSphere(isGetAll) {
		if (this.viewer.scene.layers.layerQueue.length <= 0) {
			return undefined;
		}
		let layers = [];
		if (!isGetAll) {
			layers = [this.clipLayers[0]];
		} else {
			layers = this.clipLayers;
		}
		var bounds = [];
		for (const layer of layers) {
			var rootEntities = layer._layerScheduler._rootEntities;
			for (const item of rootEntities) {
				bounds.push(item._boundingSphere);
			}
		}
		return Cesium.BoundingSphere.fromBoundingSpheres(bounds);
	}

	start() {
		const _that = this;
		this.clipLayers = this.viewer.scene.layers.layerQueue;
		if (this.clipLayerLimited.length > 0) {
			this.clipLayers = [];
			for (const name of this.clipLayerLimited) {
				const layer = this.viewer.scene.layers.find(name);
				layer && this.clipLayers.push(layer);
			}
		}
		switch (this.mode) {
			case 0: {
				this.handler = new Cesium.DrawHandler(this.viewer, Cesium.DrawMode.Box);
				this.handler.activeEvt.addEventListener((isActive) => {
					if (isActive) {
						this.viewer.enableCursorStyle = true;
						this.viewer._element.style.cursor = 'Crosshair';
					} else {
						this.viewer.enableCursorStyle = false;
						this.viewer._element.style.cursor = '';
					}
				});
				this.handler.drawEvt.addEventListener((e) => {
					const boxEntity = e.object;
					_that.setEditBox(boxEntity);
					_that.handler.clear();
					_that.handler.deactivate();
				});
				this.handler.activate();
				break;
			}
			case 1: {
				const bound = _that.getBoundingSphere(false);
				const boxEntity = this.dataSource.entities.add({
					show: false,
					position: bound.center,
					box: {
						dimensions: new Cesium.Cartesian3(bound.radius, bound.radius, bound.radius),
						outline: true,
						outlineColor: Cesium.Color.fromCssColorString('#23bbfc'),
						outlineWidth: 2,
						fill: false
					}
				});
				_that.setEditBox(boxEntity);
				break;
			}
		}
	}

	cancel() {
		this.dataSource.entities.removeAll();
		this.viewer.dataSources.remove(this.dataSource);
		this.viewer.clipBox && this.viewer.clipBox.deactivate();
		this.handler && this.handler.clear();
		this.handler && this.handler.deactivate();
		this.clearLayersClipOptions();
		this.viewer.scene.layers.layerQueue.forEach((item) => {
			item.selectEnabled = true;
		});
	}
}
ClipByBoxTool.toolId = 'ClipByBoxTool';
